package org.gd.hellocrypt;

import bitis.provider.BitisECProvider;
import bitis.provider.cipher.GostcipherPBE;

import java.security.Security;

/**
 *
 * @author omelchenko v.v.
 */
public class Crypto
{

    private static final int _encrypt = 0;
    private static final int _decrypt = 1;
    private static String strHexVal = "0123456789abcdef";
    private String salt = "hKMvRdfppLJK";

    public Crypto()
    {
    }

    /**
     * пїЅпїЅпїЅпїЅпїЅпїЅпїЅ пїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅ пїЅпїЅпїЅпїЅпїЅ пїЅпїЅпїЅпїЅпїЅ
     * @param data	пїЅпїЅпїЅпїЅпїЅ пїЅпїЅпїЅпїЅпїЅ
     * @param pwd	пїЅпїЅпїЅпїЅпїЅпїЅ
     * @return          пїЅпїЅпїЅпїЅпїЅпїЅпїЅ пїЅпїЅпїЅпїЅпїЅпїЅпїЅ пїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅ пїЅпїЅпїЅ пїЅпїЅпїЅпїЅ String.
     */
    public String Encrypt(String data, String pwd) throws Exception
    {
        Security.addProvider(new BitisECProvider());
        GostcipherPBE cipher = new GostcipherPBE(pwd+salt);
        byte[] raw = cipher.encryptCFB(data.getBytes(), _encrypt);
        return convertByteArrayToString(raw);
    }

    /**
     * пїЅпїЅпїЅпїЅпїЅпїЅпїЅ пїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅ пїЅпїЅпїЅпїЅпїЅ пїЅпїЅпїЅпїЅпїЅ
     * @param data	пїЅпїЅпїЅпїЅпїЅ пїЅпїЅпїЅпїЅпїЅ
     * @param pwd	пїЅпїЅпїЅпїЅпїЅпїЅ
     * @return          пїЅпїЅпїЅпїЅпїЅпїЅпїЅ пїЅпїЅпїЅпїЅпїЅпїЅпїЅ пїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅ пїЅпїЅпїЅ пїЅпїЅпїЅпїЅ String.
     */
    public String Decrypt(String data, String pwd) throws Exception
    {
        Security.addProvider(new BitisECProvider());
        byte[] b = convertStringToByteArray(data);
        GostcipherPBE cipher = new GostcipherPBE(pwd+salt);
        byte[] raw = cipher.encryptCFB(b, _decrypt);
        return new String(raw);
    }

    /**
     * пїЅпїЅпїЅпїЅпїЅпїЅпїЅ пїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅ String пїЅ byte[]
     * @param str  пїЅпїЅпїЅ пїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅ пїЅпїЅ пїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅ пїЅпїЅпїЅпїЅпїЅпїЅпїЅ convertByteArrayToString
     * @return пїЅпїЅпїЅпїЅпїЅ byte[]
     */
    public byte[] convertStringToByteArray(String str)
    {
        str = str.toLowerCase();
        byte[] byteConverted = new byte[(str.length() + 1) / 2];
        int j = 0;
        int interimVal;
        int nibble = -1;

        for (int i = 0; i < str.length(); ++i)
        {
            interimVal = strHexVal.indexOf(str.charAt(i));
            if (interimVal >= 0)
            {
                if (nibble < 0)
                {
                    nibble = interimVal;
                } else
                {
                    byteConverted[j++] = (byte) ((nibble << 4) + interimVal);
                    nibble = -1;
                }
            }
        }

        if (nibble >= 0)
        {
            byteConverted[j++] = (byte) (nibble << 4);
        }

        if (j < byteConverted.length)
        {
            byte[] byteTemp = new byte[j];
            System.arraycopy(byteConverted, 0, byteTemp, 0, j);
            byteConverted = byteTemp;
        }

        return byteConverted;
    }

    /**
     * пїЅпїЅпїЅпїЅпїЅпїЅпїЅ пїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅ byte[] пїЅ String
     * @param block пїЅпїЅпїЅ пїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅ пїЅпїЅ пїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅ пїЅпїЅпїЅпїЅпїЅпїЅпїЅ convertStringToByteArray
     * @return пїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅ пїЅпїЅпїЅ
     */
    private String convertByteArrayToString(byte[] block)
    {
        StringBuilder buf = new StringBuilder();

        for (byte aBlock : block) {
            buf.append(strHexVal.charAt((aBlock >>> 4) & 0xf));
            buf.append(strHexVal.charAt(aBlock & 0xf));
        }

        return buf.toString();
    }
}